﻿#pragma once

#include "precomp.h"
#include "bullet.h"
#include "enemy.h"
#include "effect.h"
#include "renders.h"
#include "sound.h"
#include "dialog.h"
#include "player.h"
#include "global_state.h"

#include "muParser.h"

using namespace mu;
using namespace std;

#ifdef _DEBUG
#pragma comment(lib, "muparserd32.lib")
#else
#pragma comment(lib, "muparser32.lib")
#endif

class Bullet;
class Effect;
class Enemy;
class EnemyBoss;


// Класс выражений
class ExpressionDescriptor{
public:
	ExpressionDescriptor();
	~ExpressionDescriptor();

	double GetValue();
	void Init();
public:
	char type; // 0 - число, 1 - выражение
	double value; // type 0
	CL_SharedPtr<Parser> exp_parser; // type 1

	CL_SharedPtr<double> rank;
	CL_SharedPtr<double> p1;
	CL_SharedPtr<double> p2;
	CL_SharedPtr<double> p3;
	CL_SharedPtr<double> p4;
	CL_SharedPtr<double> p5;
	CL_SharedPtr<double> p6;
	CL_SharedPtr<double> p7;
	CL_SharedPtr<double> p8;
	CL_SharedPtr<double> p9;
};

// Класс объекта действия
class ActionDescriptor{
public:
	char type;
	ExpressionDescriptor _param;
	char _param_type;
	ExpressionDescriptor _param2;
	char _param_type2;
	ExpressionDescriptor _param3;
	char _param_type3;
	int action;
	char params_to_pass;
	ExpressionDescriptor params[10];

	int param_location;
};

// Класс для объектов паттернов
// Управляет игровыми объектами, любыми
class BulletMLPattern{
public:
	BulletMLPattern();
	~BulletMLPattern();

	int params_needed; // Сколько параметров необходимо для управления пулей/объектом
	std::vector<ActionDescriptor> actions; // Список выполняемых действий
	double temp_params[9]; // временные хранилища параметров
	double last_bullet_speed;
	double last_bullet_direction;
public:
	void InitGameObject(GameObject* target); // создание массива параметров в управляемом объекте
	void Update(Bullet* b); // Рассчёт движения на один фрейм
	void FillExpressionParameters(ExpressionDescriptor &ex, GameObject* b);
};

// Класс хранения описаний выстрелов
class FireDescriptor{
public:
	FireDescriptor();
	~FireDescriptor();
public:
	ExpressionDescriptor speed;
	ExpressionDescriptor direction;
	char direction_type; // 0 - aim, 1 - absolute, 2 - relative, 3 - sequence
	char is_bullet_defined;
	int bullet;
	char params_to_pass;
	ExpressionDescriptor params[10];
};

// Класс описаний пуль
class BulletDescriptor{
public:
	BulletDescriptor();
	~BulletDescriptor();
public:
	ExpressionDescriptor speed;
	ExpressionDescriptor direction;
	char direction_type; // 0 - aim, 1 - absolute, 2 - relative, 3 - sequence
	char control_type; // есть ли у пули управляющий скрипт
	int action; // управляющий скрипт
	char params_to_pass;
	ExpressionDescriptor params[10];
};

// Хранилище паттернов
// Загружает, обрабатывает и выдаёт по запросу объекты паттернов
class BulletMLManager{
public:
	BulletMLManager();
	~BulletMLManager();
	BulletMLPattern* GetPatternByID(int p_id);
	BulletMLPattern* GetPatternByName(CL_String name);
	void LoadPatterns(CL_DomDocument &doc);

	BulletDescriptor ProcessBulletElement(CL_DomElement &el);
	FireDescriptor ProcessFireElement(CL_DomElement &el);
	void ProcessActionElement(CL_DomElement &el, BulletMLPattern* action);

	ExpressionDescriptor GetParsedExpression(CL_String &expr);

	Parser parser;
private:
	std::map<std::string, int> pattern_names;
	std::map<std::string, int> fire_names;
	std::map<std::string, int> bullet_names;
	std::vector<CL_SharedPtr<BulletMLPattern>> patterns;
	std::vector<FireDescriptor> fires;
	std::vector<BulletDescriptor> bullets;
	int bullet_index;
	int fire_index;
	int pattern_index;

	std::vector<std::pair<int, CL_String>> bullets_to_check;
	std::vector<std::pair<int, std::pair<int, CL_String>>> actions_to_check;
};

extern BulletMLManager bulletml;
